import {
	IAppViewMsgHelper,
	IContext,
	IDEDataSetViewMsg,
	IParam,
	isExistAndNotEmpty,
	IViewMsg,
	IViewMsgGroup,
	IViewMsgGroupDetail,
} from '@/core';
import { AppViewMsgHelperBase } from '@/core/modules/view-msg';
import { ascSort, descSort } from 'qx-util';

export class AppViewMsgHelper
	extends AppViewMsgHelperBase
	implements IAppViewMsgHelper
{
	/**
	 * 单例服务
	 *
	 * @protected
	 * @static
	 * @type {IAppViewMsgHelper}
	 * @memberof AppViewMsgHelperBase
	 */
	private static service: IAppViewMsgHelper;

	/**
	 * 获取实例
	 *
	 * @static
	 * @return {*}  {IAppViewMsgHelper}
	 * @memberof AppViewMsgHelperBase
	 */
	static getInstance(): IAppViewMsgHelper {
		if (!this.service) {
			this.service = new AppViewMsgHelper();
		}
		return this.service;
	}

	/**
	 * 视图消息缓存(加载中)
	 *
	 * @type {Map<string,any>}
	 * @memberof AppViewMsgHelper
	 */
	public static messageCache: Map<string, any> = new Map();

	/**
	 * 视图消息缓存(已完成)
	 *
	 * @type {Map<string, { result: any[], expirationTime?: number }>}
	 * @memberof AppViewMsgHelper
	 */
	public static messageCached: Map<
		string,
		{ result: any[]; expirationTime?: number }
	> = new Map();

	/**
	 * 获取视图消息集合
	 *
	 * @memberof AppViewMsgHelper
	 */
	public async getViewMsgDetails(
		tag: string,
		context?: IContext,
		viewParams?: IParam
	): Promise<any[]> {
		//  根据tag 获取视图消息
		const viewMessageGroup = App.getAppViewMsgConfig()[tag] as IViewMsgGroup;
		if (!viewMessageGroup) return [];
		const viewMsgGroupDetails: Array<IViewMsgGroupDetail> =
			viewMessageGroup?.viewMsgGroupDetails || [];
		if (viewMsgGroupDetails.length == 0) {
			return [];
		}
		const viewMsgs: any[] = [];
		for (let i = 0; i < viewMsgGroupDetails.length; i++) {
			const viewMsg = viewMsgGroupDetails[i].viewMsg;
			let items: any[] = [];
			if (viewMsg?.dynamicMode == 0) {
				//  动态模式为 静态
				items = await this.getStaticViewMessage(viewMsg, context, viewParams);
			} else if (viewMsg?.dynamicMode == 1) {
				//  动态模式为 实体数据集
				items = await this.getDynamicViewMessage(
					viewMsg as IDEDataSetViewMsg,
					context,
					viewParams
				);
			}
			viewMsgs.push(...items);
		}
		return viewMsgs;
	}

	/**
	 * 获取动态模式（静态）类型视图消息
	 *
	 * @param {IViewMsg} 动态模式（静态）类型视图消息实例
	 * @memberof AppViewMsgHelper
	 */
	public async getStaticViewMessage(
		detail: IViewMsg,
		context?: IContext,
		viewParams?: IParam
	): Promise<any[]> {
		const _this: any = this;
		return new Promise((resolve: any, reject: any) => {
			const viewMessage: any = {
				position: detail.position || 'TOP',
				name: detail.name,
				codeName: detail.codeName?.toLowerCase(),
				type: detail.messageType,
				title: detail.title,
				titleLanResTag:
					detail.titleLanResTag || detail.titlePSLanguageRes?.lanResTag,
				content: detail.message,
				removeMode: detail.removeMode,
				enableRemove: detail.enableRemove,
			};
			_this.translateMessageTemp(viewMessage, detail, context, viewParams);
			resolve([viewMessage]);
		});
	}

	/**
	 * 获取动态模式（静态）类型视图消息模板标题和内容
	 *
	 * @target {*} target 返回目标数据
	 * @param {IViewMsg} 动态模式（静态）视图消息实例
	 *
	 * @memberof AppViewMsgHelper
	 */
	public translateMessageTemp(
		target: any,
		detail: IViewMsg,
		context?: IContext,
		viewParams?: IParam,
		item?: any
	) {
		const format = (content: any) => {
			if (!isExistAndNotEmpty(content)) {
				return content;
			}
			const params: any[] = content.match(/\${(.+?)\}/g) || [];
			if (params.length > 0) {
				params.forEach((param: any) => {
					const _param: any = param
						.substring(2, param.length - 1)
						.toLowerCase();
					const arr: string[] = _param.split('.');
					if (arr.length == 2) {
						switch (arr[0]) {
							case 'context':
								content = context
									? content.replace(param, context[arr[1]])
									: content;
								break;
							case 'viewparams':
								content = viewParams
									? content.replace(param, viewParams[arr[1]])
									: content;
								break;
							case 'item':
							case 'data':
								content = item ? content.replace(param, item[arr[1]]) : content;
								break;
						}
					}
				});
			}
			return content;
		};
		const appMsgTempl = detail.msgTempl;
		if (!appMsgTempl) {
			return;
		}
		Object.assign(target, {
			messageType: appMsgTempl.contentType == 'HTML' ? 'HTML' : 'TEXT',
			title: format(appMsgTempl.subject),
			titleLanResTag: appMsgTempl.subPSLanguageRes?.lanResTag,
			content: format(appMsgTempl.content),
		});
	}

	/**
	 * 初始化动态模式（实体数据集合）类型视图消息
	 *
	 * @param {any} tag 视图消息标识
	 * @param {any} messageService 消息服务
	 * @param {string} context
	 * @returns {Promise<any[]>}
	 * @memberof AppViewMsgHelper
	 */
	public async getDynamicViewMessage(
		detail: IDEDataSetViewMsg,
		context: any = {},
		viewParams: any = {},
		isloading?: boolean
	): Promise<any[]> {
		if (context && context.srfsessionid) {
			delete context.srfsessionid;
		}
		//  动态模式（实体数据集合）类型视图消息服务
		return new Promise((resolve: any, reject: any) => {
			const isEnableCache: boolean = (detail as any).enableCache;
			const cacheTimeout: any = (detail as any).cacheTimeout;
			const tag: any = detail.codeName;
			// 启用缓存
			if (isEnableCache) {
				const callback: Function = (
					context: any = {},
					data: any = {},
					tag: string,
					promise: Promise<any>
				) => {
					promise
						.then((result: any) => {
							if (result.length > 0) {
								AppViewMsgHelper.messageCached.set(tag, {
									result,
									expirationTime: new Date().getTime() + cacheTimeout,
								});
								AppViewMsgHelper.messageCache.delete(tag);
								return resolve(result);
							} else {
								return resolve([]);
							}
						})
						.catch((result: any) => {
							return reject(result);
						});
				};
				// 加载完成,从本地缓存获取
				const activeViewMsg = AppViewMsgHelper.messageCached.get(tag);
				if (activeViewMsg) {
					const items: any = activeViewMsg.result;
					if (items.length > 0 && activeViewMsg?.expirationTime) {
						if (new Date().getTime() <= activeViewMsg.expirationTime) {
							return resolve(items);
						}
					}
				}
				// 加载中，UI又需要数据，解决连续加载同一消息服务问题
				if (AppViewMsgHelper.messageCache.get(tag)) {
					callback(
						context,
						viewParams,
						tag,
						AppViewMsgHelper.messageCache.get(tag)
					);
				} else {
					const result: Promise<any> = this.getItems(
						detail,
						context,
						viewParams
					);
					AppViewMsgHelper.messageCache.set(tag, result);
					callback(context, viewParams, tag, result);
				}
			} else {
				this.getItems(detail, context, viewParams)
					.then((result: any) => {
						resolve(result);
					})
					.catch((error: any) => {
						Promise.reject([]);
					});
			}
		});
	}

	/**
	 * 获取远程数据
	 *
	 * @param {*} context 应用上下文
	 * @param {*} data 视图参数
	 * @param {boolean} [isloading] 加载状态
	 * @returns {Promise<any>}
	 *
	 * @memberof AppViewMsgHelper
	 */
	public getItems(
		detail: IDEDataSetViewMsg,
		context: any = {},
		viewParams: any = {}
	): Promise<any> {
		const _this = this;
		const appDataEntityCodeName = detail.psAppDataEntity?.codeName;
		const appDataSetCodeName = detail.psAppDEDataSet?.codeName;
		const tempContext: any = context ? context : {};
		const tempData: any = viewParams ? viewParams : {};
		return new Promise((resolve, reject) => {
			if (appDataEntityCodeName && appDataSetCodeName) {
				App.getDataService(appDataEntityCodeName, context).then(
					(service: any) => {
						if (service && service[appDataSetCodeName] instanceof Function) {
							const promise: Promise<any> = service[appDataSetCodeName](
								tempContext,
								tempData
							);
							promise
								.then((response: any) => {
									if (response.success) {
										const data = response.data;
										resolve(_this.doItems(detail, data, tempContext, tempData));
									} else {
										resolve([]);
									}
								})
								.catch((response: any) => {
									console.error(response);
									reject(response);
								});
						}
					}
				);
			} else {
				resolve([]);
			}
		});
	}

	/**
	 * 处理数据
	 *
	 * @param {any[]} items 源数据
	 * @param {*} context 应用上下文
	 * @param {*} data 视图参数
	 * @returns {any[]}
	 *
	 * @memberof AppViewMsgHelper
	 */
	public doItems(
		detail: IDEDataSetViewMsg,
		items: any[],
		context: any = {},
		data: any = {}
	): any[] {
		const _this = this;
		const tempItems: any[] = [];
		const {
			name,
			codeName,
			title,
			position,
			titleLanResTag,
			message,
			messageType,
			removeMode,
			enableRemove,
		} = detail;
		if (items.length > 0) {
			//  排序
			if (detail.orderValuePSAppDEField?.codeName) {
				_this.sortItems(detail, items);
			}
			items.forEach((item: any) => {
				const tempData: any = {
					position: position || 'TOP',
					name: name,
					codeName: codeName?.toLowerCase(),
					type: messageType,
					title: title,
					titleLanResTag:
						titleLanResTag || detail.titlePSLanguageRes?.lanResTag,
					content: message,
					removeMode: removeMode,
					enableRemove: enableRemove,
				};
				_this.formatDynamicViewMsg(detail, tempData, context, data, item);
				_this.translateMessageTemp(tempData, detail, context, data, item);
				tempItems.push(tempData);
			});
		}
		return tempItems;
	}

	/**
	 * 根据属性配置翻译视图消息
	 *
	 * @target {*} target 返回目标数据
	 * @param {*} context 应用上下文
	 * @param {*} viewParams 视图参数
	 *
	 * @memberof AppViewMsgHelper
	 */
	public formatDynamicViewMsg(
		detail: IDEDataSetViewMsg,
		target: any,
		context: any = {},
		viewParams: any = {},
		item?: any
	) {
		if (!item) {
			return;
		}
		//  标题
		const titleField = detail.titlePSAppDEField?.codeName?.toLowerCase();
		if (titleField && item[titleField]) {
			Object.assign(target, { title: item[titleField] });
		}
		//  内容
		const contentField = detail.contentPSAppDEField?.codeName?.toLowerCase();
		if (contentField && item[contentField]) {
			Object.assign(target, { content: item[contentField] });
		}
		//  消息类型
		const msgTypeField = detail.msgTypePSAppDEField?.codeName?.toLowerCase();
		if (msgTypeField) {
			const type = item[msgTypeField];
			if (
				type == 'INFO' ||
				item[msgTypeField] == 'WARN' ||
				type == 'ERROR' ||
				type == 'CUSTOM'
			) {
				Object.assign(target, { type: type });
			} else {
				console.warn(
					"视图消息类型值异常，应为['INFO', 'WARN', 'ERROR', 'CUSTOM']中的类型"
				);
			}
		}
		//  消息位置
		const msgPosField = detail.msgPosPSAppDEField?.codeName?.toLowerCase();
		if (msgPosField) {
			const position = item[msgPosField];
			if (
				position == 'TOP' ||
				position == 'BODY' ||
				position == 'BOTTOM' ||
				position == 'POPUP' ||
				position == 'CUSTOM'
			) {
				Object.assign(target, { position: position });
			} else {
				console.warn(
					"视图消息位置值异常，应为['TOP', 'BODY', 'BOTTOM', 'POPUP', 'CUSTOM']中的位置"
				);
			}
		}
		//  删除模式
		const removeFlagField =
			detail.removeFlagPSAppDEField?.codeName?.toLowerCase();
		if (removeFlagField) {
			const removeMode = item[removeFlagField];
			if (removeMode == 0 || removeMode == 1 || removeMode == 2) {
				Object.assign(target, { removeMode: removeMode });
			} else {
				console.warn(
					"视图消息删除模式值异常，应为[0, 1, 2]中的值，分别表示['无关闭', '默认关闭', '本次关闭']"
				);
			}
		}
		//  排序标识
		const orderValueField =
			detail.orderValuePSAppDEField?.codeName?.toLowerCase();
		if (orderValueField && item[orderValueField]) {
			Object.assign(target, { orderKey: item[orderValueField] });
		}
		//  标题多语言
		const titleLanResTagField =
			detail.titleLanResTagPSAppDEField?.codeName?.toLowerCase();
		if (titleLanResTagField && item[titleLanResTagField]) {
			Object.assign(target, { titleLanResTag: item[titleLanResTagField] });
		}
	}

	/**
	 * 排序(默认升序)
	 *
	 * @param items
	 */
	public sortItems(detail: IDEDataSetViewMsg, items: any[], mode = 'ASC') {
		const orderValue = detail.orderValuePSAppDEField?.codeName.toLowerCase();
		if (mode == 'ASC') {
			items = ascSort(items, orderValue);
		} else {
			items = descSort(items, orderValue);
		}
	}
}
